package module

import (
	"context"

	"go.uber.org/atomic"
	"hundsun.com/hsl/hschain/common/config"
	"hundsun.com/hsl/hschain/common/log/logging"
	"hundsun.com/hsl/hschain/module/common/utils"
	"hundsun.com/hsl/hschain/module/registry"
	pbcommon "hundsun.com/hsl/hschain/protos/common"
)

const configParamLogLevel = "logLevel"

var registryService = registry.GetRegistryServiceInstance()

//StartupFunc 模块启动函数，
type StartupFunc func(startedInterestedModules map[string][]*registry.ModRegKV) error

// CompeteMasterCallback 模块CompeteMaster方法调用后回调，菜蔬
type CompeteMasterCallback func(hasMasterLock bool)

// Adapter 模块适配器。子类实例化后，必须先调用Init方法。
type Adapter struct {
	name                  string
	interestedModules     []string
	startupFunc           StartupFunc
	CompeteMasterCallback CompeteMasterCallback
	Config                *config.ModuleConfig
	Status                Status
	StatusErrReason       error
	ListenAddress         *pbcommon.NetworkAddress
	Log                   logging.Log
	RootCtx               context.Context
	RootCtxCancelFunc     context.CancelFunc
	HasMasterLock         *atomic.Bool
}

// Init ModuleAdapter子类实例化后，首先应该调用此方法
func (m *Adapter) Init(moduleName string, interestedModules []string, moduleStartupFunc StartupFunc) {
	m.name = moduleName
	m.interestedModules = interestedModules
	m.startupFunc = moduleStartupFunc
	m.HasMasterLock = atomic.NewBool(false)
}

//Name ...
func (m *Adapter) Name() string {
	return m.name
}

//GetStatus 获取状态
func (m *Adapter) GetStatus() (Status, error) {
	return m.Status, m.StatusErrReason
}

//Startup 模块启动
func (m *Adapter) Startup(config *config.ModuleConfig) (status Status, err error) {
	m.Config = config
	// 初始化logger
	var logLevel logging.LogLevel
	logLevelStr := utils.GetStringConfigParameterValue(m.Config, configParamLogLevel, "INFO")
	logLevel, err = logging.ParseLevel(logLevelStr)
	m.Log = logging.NewLog(logLevel, logging.LogFieldModule, m.Name())

	log := m.Log
	log.Info("starting up...", config.ModuleName)

	//在defer函数中判断启动是否成功
	defer func() {
		m.StatusErrReason = err
		if err != nil {
			m.Status = StatusError
			log.Errorf("failed to start up: %s", err.Error())
		} else {
			m.Status = StatusRunning
			log.Info("started")
		}
		status = m.Status
	}()

	// TODO 新版本不需要监听地址, 通过mq进行通信
	//解析模块监听地址
	m.ListenAddress, err = utils.ParseListenAddress(m.Config)
	if err != nil {
		return
	}
	if m.ListenAddress != nil {
		log.Info("listen address:", m.ListenAddress.Format())
	}
	m.RootCtx, m.RootCtxCancelFunc = context.WithCancel(context.Background())

	// TODO 之前用etcd进行感兴趣模块处理目前mq下不需要感兴趣模块
	startedInterestedModules := make(map[string][]*registry.ModRegKV)

	err = m.startupFunc(startedInterestedModules)
	return
}

//GetRegisteredKV 获取注册key-value
func (m *Adapter) GetRegisteredKV() (*registry.ModRegKV, error) {
	return registryService.ConvertModuleConfig2ModRegKV(m.Config)
}

// IsMasterStandbyMode 是否是master/standby模式
func (m *Adapter) IsMasterStandbyMode() bool {
	return true
}

// IsMaster 是否是master
/*func (m *Adapter) IsMaster() bool {
	return true
}*/

// CompeteMaster 竞争master
/*func (m *Adapter) CompeteMaster() (bool, error) {
	m.Log.Debugf("%s competing master", m.Config.ModuleID)
	return true, nil
}*/

//Shutdown 模块close
func (m *Adapter) Shutdown() (Status, error) {
	return m.Status, nil
}

//GetInterestedModules ...
func (m *Adapter) GetInterestedModules() []string {
	return m.interestedModules
}

//OnInterestedModuleUp ...
func (m *Adapter) OnInterestedModuleUp(kv *registry.ModRegKV) (Status, error) {
	return m.Status, nil
}

//OnInterestedModuleDown ...
func (m *Adapter) OnInterestedModuleDown(preKV *registry.ModRegKV) (Status, error) {
	return m.Status, nil
}
